
    // TODO test!!

    HashMap.implement
    (
        new function closure () 
        {
            
            /**
             * @private
             * Assert that this maps keys and values are synchronized.
             * 
             * @throws {RangeError}
             */
            function validate () 
            {
                if (this.keys.length !== this.values.length)
                    throw new RangeError('MapSynchronizationError');
            };
            
            this.constructor.implement
            (
                {
                    /**
                     * The maps keys
                     * @type {Array}
                     */
                    keys: null
                    
                    /**
                     * The maps values
                     * @type {Array}
                     */            
                ,   values: null
                    
                    /**
                     * Put a value in the map, associating it with a key. If the
                     * key is already in use, 
                     * 
                     * @param {Object} key
                     * @param {Object} value
                     * @returns {void}
                     * @throws {RangeError}    If the map is invalid.
                     */
                ,   put: function (key, value) 
                    {
                        validate.call(this);
                        var index= this.keys.indexOf(key);
                        if (-1 === index) 
                        {
                            this.keys.push(key);
                            this.values.push(value);
                            return;
                        }
                        
                        // not tested- probably broken
                        this.keys.splice(index, 1, key);
                        this.values.splice(index, 1, value);
                    }
                    
                    /**
                     * Retrieve a value from the map by using a key.
                     * 
                     * @param {Object} key
                     * @return {Object}
                     * @throws {RangeError}    If the map is invalid.
                     * @throws {RangeError}    If the key is not in use by the map.
                     */
                ,   get: function (key) 
                    {
                        validate.call(this);
                        var index= this.keys.indexOf(key);
                        
                        if (index > -1)
                            return this.values[index];    
                            
                        throw new RangeError ('UndefinedKey:' + key);
                    }
                    
                    /**
                     * Determine if the map has a certain key.
                     * 
                     * @param {Object} key
                     * @return {Boolean}
                     * @throws {RangeError}
                     */
                ,   has: function (key) 
                    {
                        validate.call(this);
                        return -1 < this.keys.indexOf(key);
                    }
                    
                    /**
                     * Determine if the map contains a value.
                     * 
                     * @param {Object} value
                     * @return {Boolean}
                     * @throws {RangeError}
                     */
                ,   contains: function (value) 
                    {
                        validate.call(this);
                        return -1 < this.values.indexOf(value);
                    }
                    
                    /**
                     * Determine the size of a map.
                     * 
                     * @return {Number}
                     * @throws {RangeError}
                     */
                ,   size: function () 
                    {
                        validate.call(this);
                        return this.keys.length;
                    }
                    
                    /**
                     * Remove a key value pair from the map
                     * 
                     * @param {Object} key
                     * @return {void}
                     */
                ,   remove: function (key) 
                    {
                        validate.call(this);
                        var index= this.keys.indexOf(key);
                        
                        if (-1 === index)
                            return;
                            
                        this.values.splice(index, 1);
                        this.keys.splice(index, 1);
                    } 
                    
                    /**
                     * Get the keys in use by this map
                     * 
                     * @return {Array}
                     */
                ,   getKeys: function () 
                    {
                        return this.keys.concat(); // clone
                    }
                    
                    /**
                     * Get the values in use by this map
                     * 
                     * @return {Array}
                     */
                ,   getValues: function () 
                    {
                        return this.values.concat(); // clone
                    }
                    
                    /**
                     * Discard all keys and values being used by this map
                     * 
                     * @return {void}
                     */
                ,   clear: function () 
                    {
                        this.keys= [];
                        this.values= [];
                    }
                    
                    /**
                     * Determine if the map is empty.
                     * 
                     * @returns {Boolean}
                     */
                ,   isEmpty: function () 
                    {
                        return 0 === this.size();
                    }
                    
                    /**
                     * Determine if this maps integrity is ok or not.
                     * @returns {Boolean}
                     */
                ,   isValid: function () 
                    {
                        try 
                        {
                            validate.call(this);
                            return true;
                        }
                        catch (thrown) 
                        {
                            return false;
                        }
                    }
                }  
            )
        }
    );
    
    function HashMap () 
    {
        this.clear();
    };